#include "toastnotification.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPixmap>
#include <QScreen>
#include <QApplication>
#include <QDebug>
#include <QPainter>

// 静态常量定义
const int ToastNotification::MIN_TOAST_WIDTH;
const int ToastNotification::MAX_TOAST_WIDTH_RATIO;
const int ToastNotification::TOAST_PADDING;
const int ToastNotification::TOAST_SPACING;
const int ToastNotification::CORNER_RADIUS;
const int ToastNotification::FONT_SIZE_BASE;

// 单例初始化
ToastNotification* ToastNotification::s_instance = nullptr;

// Toast堆叠管理初始化
int ToastNotification::s_toastCount = 0;

ToastNotification::ToastNotification(QWidget* parent)
    : QWidget(parent)
    , m_messageLabel(nullptr)
    , m_showAnimation(nullptr)
    , m_hideAnimation(nullptr)
    , m_scaleAnimation(nullptr)
    , m_autoHideTimer(nullptr)
    , m_currentType(ToastType::Info)
{
    setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);

    // 设置现代化毛玻璃效果
    setAttribute(Qt::WA_ShowWithoutActivating);
    setAttribute(Qt::WA_TranslucentBackground); // 支持透明度和毛玻璃效果

    // 设置objectName确保样式选择器生效
    setObjectName("toastNotification");

    // 不使用QGraphicsOpacityEffect，改用windowOpacity动画
    // 这样不会影响背景色的显示
    setWindowOpacity(0.0);

    // 创建动画 - 直接对窗口透明度做动画
    m_showAnimation = new QPropertyAnimation(this, "windowOpacity", this);
    m_showAnimation->setDuration(300);
    m_showAnimation->setStartValue(0.0);
    m_showAnimation->setEndValue(0.95); // 轻微透明保持背景可见

    m_hideAnimation = new QPropertyAnimation(this, "windowOpacity", this);
    m_hideAnimation->setDuration(300);
    m_hideAnimation->setStartValue(0.95);
    m_hideAnimation->setEndValue(0.0);

    // 添加缩放动画 - 现代化效果
    m_scaleAnimation = new QPropertyAnimation(this, "geometry", this);
    m_scaleAnimation->setDuration(250);
    m_scaleAnimation->setEasingCurve(QEasingCurve::OutBack);

    // 自动隐藏定时器
    m_autoHideTimer = new QTimer(this);
    connect(m_autoHideTimer, &QTimer::timeout, this, &ToastNotification::animateHide);
    connect(m_hideAnimation, &QPropertyAnimation::finished, this, &ToastNotification::onAnimationFinished);
}

ToastNotification::~ToastNotification()
{
    // Qt会自动清理子对象
}

void ToastNotification::setupUI(ToastType type, const QString& message)
{
    // 存储toast类型以便paintEvent使用
    m_currentType = type;

    // 计算动态尺寸
    QSize optimalSize = calculateOptimalSize(message);
    setFixedSize(optimalSize);

    // 应用现代化毛玻璃样式
    setStyleSheet(getModernStyleSheet(type));

    // 创建主布局 - 现代化设计
    QVBoxLayout* mainLayout = new QVBoxLayout(this);
    mainLayout->setContentsMargins(TOAST_PADDING, TOAST_PADDING, TOAST_PADDING, TOAST_PADDING);
    mainLayout->setSpacing(TOAST_SPACING);

    // 创建内容布局（图标 + 文字）
    QHBoxLayout* contentLayout = new QHBoxLayout();
    contentLayout->setSpacing(TOAST_SPACING);

    // 添加现代化图标
    QLabel* iconLabel = new QLabel(getToastIcon(type), this);
    QString iconStyle = QString(
        "QLabel {"
        "    font-size: %1px;"
        "    background-color: transparent;"
        "    border: none;"
        "}"
    ).arg(getDPIScaledSize(20));
    iconLabel->setStyleSheet(iconStyle);
    iconLabel->setFixedSize(getDPIScaledSize(24), getDPIScaledSize(24));
    iconLabel->setAlignment(Qt::AlignCenter);

    // 创建消息标签 - 现代化文字样式
    m_messageLabel = new QLabel(message, this);
    m_messageLabel->setWordWrap(true);
    m_messageLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); // 改为Top对齐，多行文本更自然
    m_messageLabel->setMinimumWidth(200); // 设置最小宽度确保文本显示
    // 移除最大宽度限制，让容器控制宽度
    QString messageStyle = QString(
        "QLabel {"
        "    color: #333333;"
        "    font-size: %1px;"
        "    font-weight: 500;"
        "    line-height: 1.5;"
        "    background-color: transparent;"
        "    border: none;"
        "    padding: 4px;"
        "}"
    ).arg(getDPIScaledSize(FONT_SIZE_BASE));
    m_messageLabel->setStyleSheet(messageStyle);

    contentLayout->addWidget(iconLabel);
    contentLayout->addWidget(m_messageLabel, 1); // 设置stretch factor为1，让消息标签占据剩余空间
    // 移除addStretch()，让消息标签能够充分利用空间

    mainLayout->addLayout(contentLayout);
}

QString ToastNotification::getStyleSheet(ToastType type) const
{
    // 保留旧方法以备兼容性需要
    return getModernStyleSheet(type);
}

QString ToastNotification::getModernStyleSheet(ToastType type) const
{
    // 现代化毛玻璃Toast样式 - 几乎完全透明，依赖paintEvent绘制
    QString baseStyle = QString(
        "QWidget#toastNotification {"
        "    background-color: transparent;"
        "    border: none;"
        "    border-radius: %1px;"
        "}"
        "QWidget#toastNotification QLabel {"
        "    background-color: transparent;"
        "    border: none;"
        "}"
    );

    return baseStyle.arg(CORNER_RADIUS);
}

void ToastNotification::animateShow()
{
    // 增加Toast计数
    s_toastCount++;
    
    // 计算最终显示位置 - 显示在窗口右下角，支持堆叠
    QRect finalGeometry;
    if (parentWidget()) {
        // 获取主窗口（MainWindow）的几何信息
        QWidget* mainWindow = parentWidget();
        while (mainWindow && !mainWindow->isWindow()) {
            mainWindow = mainWindow->parentWidget();
        }
        
        if (mainWindow) {
            QRect windowRect = mainWindow->geometry();
            
            // 计算相对于主窗口的右下角位置
            int x = windowRect.width() - width() - 20;  // 距离右边20像素
            int y = windowRect.height() - height() - 20 - (s_toastCount - 1) * (height() + 10);  // 距离底部20像素，支持堆叠
            
            // 确保坐标不为负数，并且不会超出窗口边界
            x = qMax(0, qMin(x, windowRect.width() - width()));
            y = qMax(0, qMin(y, windowRect.height() - height()));
            
            finalGeometry = QRect(x, y, width(), height());
            
            // 调试信息
        } else {
            // 回退到屏幕右下角
            QScreen* screen = QApplication::primaryScreen();
            if (screen) {
                QRect screenRect = screen->geometry();
                int x = screenRect.width() - width() - 20;
                int y = screenRect.height() - height() - 20 - (s_toastCount - 1) * (height() + 10);
                finalGeometry = QRect(x, y, width(), height());
            }
        }
    } else {
        // 如果没有父窗口，在屏幕右下角显示
        QScreen* screen = QApplication::primaryScreen();
        if (screen) {
            QRect screenRect = screen->geometry();
            int x = screenRect.width() - width() - 20;
            int y = screenRect.height() - height() - 20 - (s_toastCount - 1) * (height() + 10);
            finalGeometry = QRect(x, y, width(), height());
        }
    }

    // 设置缩放动画的起始和结束状态
    QPoint center = finalGeometry.center();
    QSize startSize = finalGeometry.size() * 0.8; // 从80%大小开始
    QRect startGeometry = QRect(center.x() - startSize.width()/2,
                                center.y() - startSize.height()/2,
                                startSize.width(), startSize.height());

    setGeometry(startGeometry);
    QWidget::show();

    // 同时播放透明度和缩放动画
    m_scaleAnimation->setStartValue(startGeometry);
    m_scaleAnimation->setEndValue(finalGeometry);
    m_scaleAnimation->start();

    m_showAnimation->start();
}

void ToastNotification::animateHide()
{
    m_hideAnimation->start();
}

// 现代化设计方法实现
QSize ToastNotification::calculateOptimalSize(const QString& message) const
{
    // 获取屏幕信息计算DPI比例
    QScreen* screen = QApplication::primaryScreen();
    int dpi = screen ? screen->logicalDotsPerInch() : 96;
    double dpiScale = static_cast<double>(dpi) / 96.0;

    // 计算文字尺寸 - 使用实际字体
    QFont font("Arial", getDPIScaledSize(FONT_SIZE_BASE));
    QFontMetrics fontMetrics(font);

    // 更精确的尺寸计算 - 提高最大宽度限制
    int screenMaxWidth = screen ? screen->geometry().width() : 1920;
    int maxWidth = qMin(screenMaxWidth * MAX_TOAST_WIDTH_RATIO / 100, 1000); // 最大1000px，增加容纳空间
    int minWidth = qMax(MIN_TOAST_WIDTH, 320); // 最小320px，确保足够的文本空间

    // 图标和间距预留
    int iconWidth = getDPIScaledSize(24);
    int spacing = getDPIScaledSize(TOAST_SPACING);
    int padding = getDPIScaledSize(TOAST_PADDING);

    // 计算文字可用宽度，增加额外缓冲
    int availableTextWidth = maxWidth - iconWidth - spacing - (padding * 2) - 10; // 增加10px缓冲

    // 使用 QFontMetrics::boundingRect 进行精确的文本尺寸计算
    QRect textBounds = fontMetrics.boundingRect(QRect(0, 0, availableTextWidth, 2000), // 增加高度限制
                                               Qt::TextWordWrap | Qt::AlignLeft | Qt::AlignVCenter,
                                               message);

    // 确保文本尺寸计算准确，增加安全边距
    int safeTextWidth = textBounds.width() + 20; // 增加20px安全边距
    int safeTextHeight = textBounds.height() + 10; // 增加10px高度边距

    // 计算最终尺寸
    int contentWidth = safeTextWidth + iconWidth + spacing + (padding * 2);
    int finalWidth = qBound(minWidth, contentWidth, maxWidth);

    // 高度计算：确保有足够的垂直空间，增加行高缓冲
    int lineHeight = fontMetrics.height();
    int lineSpacing = fontMetrics.lineSpacing();

    // 计算需要的行数 - 更准确的行数计算
    int estimatedLines = qCeil(static_cast<double>(textBounds.width()) / availableTextWidth);
    estimatedLines = qMax(estimatedLines, 1);
    if (message.contains("\n")) {
        QStringList lines = message.split("\n");
        estimatedLines = qMax(estimatedLines, lines.size());
    }

    int minTextHeight = lineSpacing * qMax(2, estimatedLines); // 根据实际行数调整最小高度
    int textHeight = safeTextHeight;
    int finalHeight = qMax(minTextHeight, textHeight) + (padding * 2) + 15; // 增加15px垂直缓冲

    // 确保最小尺寸足够容纳多行文本
    if (message.contains("\n") || message.length() > 25) {
        finalWidth = qMax(finalWidth, 420); // 对于长文本，最小宽度420px
        finalHeight = qMax(finalHeight, lineSpacing * (estimatedLines + 1) + (padding * 2)); // 预留额外行空间
    }

    return QSize(finalWidth, finalHeight);
}

int ToastNotification::getDPIScaledSize(int baseSize) const
{
    QScreen* screen = QApplication::primaryScreen();
    int dpi = screen ? screen->logicalDotsPerInch() : 96;
    return qRound(baseSize * static_cast<double>(dpi) / 96.0);
}

QString ToastNotification::getToastIcon(ToastType type) const
{
    switch (type) {
        case ToastType::Info:
            return "ℹ️";    // 信息图标
        case ToastType::Warning:
            return "⚠️";    // 警告图标
        case ToastType::Error:
            return "❌";    // 错误图标
        case ToastType::Success:
            return "✅";    // 成功图标
        default:
            return "ℹ️";
    }
}

int ToastNotification::calculateOptimalDuration(const QString& message) const
{
    // 基础显示时间
    int baseDuration = 2000; // 2秒基础时间

    // 根据文字长度调整时间
    int wordCount = message.length();
    int readingTime = qMax(1000, wordCount * 80); // 每个字符80ms阅读时间

    // 计算最终显示时间
    int finalDuration = qMax(baseDuration, readingTime);

    // 设置上限：最长6秒
    return qMin(finalDuration, 6000);
}

void ToastNotification::paintEvent(QPaintEvent* event)
{
    // 现代化毛玻璃背景绘制
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 毛玻璃背景效果 - 根据Toast类型调整颜色
    QColor glassBackground, borderColor;
    if (m_currentType == ToastType::Success) {
        glassBackground = QColor(176, 224, 230, 200); // 粉蓝色背景，与呼吸灯一致
        borderColor = QColor(135, 206, 235, 180);     // 亮蓝色边框
    } else if (m_currentType == ToastType::Error) {
        glassBackground = QColor(255, 235, 235, 200); // 淡红色背景
        borderColor = QColor(255, 150, 150, 180);     // 红色边框
    } else {
        glassBackground = QColor(255, 255, 255, 235); // 默认半透明白色
        borderColor = QColor(200, 200, 200, 150);     // 淡边框
    }

    // 绘制毛玻璃背景
    painter.setBrush(glassBackground);
    painter.setPen(QPen(borderColor, 1));
    painter.drawRoundedRect(rect().adjusted(0, 0, -1, -1), CORNER_RADIUS, CORNER_RADIUS);

    // 添加微妙的内阴影效果
    QColor innerShadow = QColor(0, 0, 0, 20);
    painter.setPen(QPen(innerShadow, 1));
    painter.drawRoundedRect(rect().adjusted(2, 2, -3, -3), CORNER_RADIUS-2, CORNER_RADIUS-2);

    QWidget::paintEvent(event);
}

void ToastNotification::onAnimationFinished()
{
    if (m_hideAnimation->state() == QPropertyAnimation::Stopped) {
        // 减少Toast计数
        s_toastCount = qMax(0, s_toastCount - 1);
        hide();
        deleteLater(); // 自动清理
    }
}

// Martin Fowler重构：静态便利方法实现
void ToastNotification::showInfo(QWidget* parent, const QString& message, int duration)
{
    ToastNotification* toast = new ToastNotification(parent);
    toast->setupUI(ToastType::Info, message);
    toast->animateShow();
    int optimalDuration = (duration > 0) ? duration : toast->calculateOptimalDuration(message);
    toast->m_autoHideTimer->start(optimalDuration);
}

void ToastNotification::showWarning(QWidget* parent, const QString& message, int duration)
{
    ToastNotification* toast = new ToastNotification(parent);
    toast->setupUI(ToastType::Warning, message);
    toast->animateShow();
    int optimalDuration = (duration > 0) ? duration : toast->calculateOptimalDuration(message);
    toast->m_autoHideTimer->start(optimalDuration);
}

void ToastNotification::showError(QWidget* parent, const QString& message, int duration)
{
    ToastNotification* toast = new ToastNotification(parent);
    toast->setupUI(ToastType::Error, message);
    toast->animateShow();
    int optimalDuration = (duration > 0) ? duration : toast->calculateOptimalDuration(message);
    toast->m_autoHideTimer->start(optimalDuration);
}

void ToastNotification::showSuccess(QWidget* parent, const QString& message, int duration)
{
    ToastNotification* toast = new ToastNotification(parent);
    toast->setupUI(ToastType::Success, message);
    toast->animateShow();
    int optimalDuration = (duration > 0) ? duration : toast->calculateOptimalDuration(message);
    toast->m_autoHideTimer->start(optimalDuration);
}

void ToastNotification::show(QWidget* parent, const QString& message, ToastType type, int duration)
{
    ToastNotification* toast = new ToastNotification(parent);
    toast->setupUI(type, message);
    toast->animateShow();
    int optimalDuration = (duration > 0) ? duration : toast->calculateOptimalDuration(message);
    toast->m_autoHideTimer->start(optimalDuration);
}

// 单例模式实现
ToastNotification* ToastNotification::instance()
{
    if (!s_instance) {
        s_instance = new ToastNotification(nullptr);
        s_instance->setupUI(ToastType::Info, ""); // 初始化样式但不显示消息
    }
    return s_instance;
}

void ToastNotification::destroyInstance()
{
    if (s_instance) {
        delete s_instance;
        s_instance = nullptr;
    }
}